﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace NeuralNetwork
{
	class Program
	{
		static void Main(string[] args)
		{
			double[,] data, trainDataSet, testDataSet;
			string s1 = "", file = "";
			string[] s2;
			int numberOfFeatures = 0, numberOfVectors = 0, tmp = 0;
			bool appropriateData = false;

			Console.WriteLine("Path to file with data:   default: \"..\\..\\..\\iris.dat\"");
			file = Console.ReadLine();

			StreamReader sr = new StreamReader(file);

			#region Getting info about data

			// get data info
			while ((s1 = sr.ReadLine()) != null)
			{
				if (s1[0] == '#')
					continue;

				// read info about data set
				if (tmp == 0)
				{
					s2 = s1.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
					numberOfFeatures = Convert.ToInt32(s2[s2.GetLength(0) - 1]);
					tmp++;
				}
				else if (tmp == 1)
				{
					s2 = s1.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
					numberOfVectors = Convert.ToInt32(s2[s2.GetLength(0) - 1]);
					tmp++;
				}
				else if (tmp == 2)
					break;
			}

			#endregion

			// initialize
			data = new double[numberOfVectors, numberOfFeatures];

			#region Reading data from file

			// read data
			int currentLine = 0;
			tmp = 0;

			while ((s1 = sr.ReadLine()) != null)
			{
				if (appropriateData)
				{
					s2 = s1.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

					for (int i = 0; i < numberOfFeatures; i++)
					{
						data[currentLine, i] = Convert.ToDouble(s2[i]);
					}

					currentLine++;

					if (currentLine >= numberOfVectors)
						break;
				}
				else
				{
					if (s1.Length > 0 && s1[0] == '[')
						appropriateData = true;
				}
			}
			sr.Close();
			Console.WriteLine("Reading was completed successfully.\n");

			#endregion

			#region Writing data on console

			/*
			// show data
			Console.WriteLine("Vectors: {0}, Columns: {1}", numberOfVectors, numberOfFeatures);
			for (int i = 0; i < numberOfVectors; i++)
			{
				for (int j = 0; j < numberOfFeatures; j++)
				{
					Console.Write(Convert.ToString(data[i, j]) + "   ");
				}
				Console.WriteLine("");
			}
			*/

			#endregion 

			#region Dividing data

			// divide data
			int numberOfTrainingVectors = (int)(0.3 * numberOfVectors);
			trainDataSet = new double[numberOfTrainingVectors, numberOfFeatures];
			testDataSet = new double[numberOfVectors - numberOfTrainingVectors, numberOfFeatures];

			for (int i = 0; i < trainDataSet.GetLength(0); i++)
			{
				for (int j = 0; j < numberOfFeatures; j++)
				{
					trainDataSet[i, j] = data[i, j];
				}
			}

			for (int i = 0; i < testDataSet.GetLength(0); i++)
			{
				for (int j = 0; j < numberOfFeatures; j++)
				{
					testDataSet[i, j] = data[i + trainDataSet.GetLength(0), j];
				}
			}

			#endregion

			double[] values = new double[3]{1.0, 2.0, 3.0};
			NeuralNetwork nn = new NeuralNetwork(trainDataSet, testDataSet, values, numberOfFeatures - 1, 1, 1, 1, (int)(0.75 * numberOfFeatures));
			nn.CreateNetwork();
			nn.TrainNetwork();

			#region Testing neural network

			Console.WriteLine("");

			int numberOfTestingVector = 70;

			for (int j = 0; j < 30; j++)
			{
				numberOfTestingVector = j + 70;

				double[] tmpVec = new double[numberOfFeatures];

				for (int i = 0; i < numberOfFeatures; i++)
					tmpVec[i] = data[numberOfTestingVector, i];

				Console.WriteLine("Vector number {0}", numberOfTestingVector);
				Console.WriteLine("Expected value: " + data[numberOfTestingVector, numberOfFeatures - 1]);
				Console.WriteLine("Obtained value: " + nn.TestVector(tmpVec));
				Console.WriteLine("");
			}

			

			#endregion

			// wait for key
			Console.WriteLine("Waiting for key...");
			Console.ReadKey();
		}
	}
}
